import React, { useEffect, useState } from 'react'; import './index.css'; import error from '../../assets/error.svg'; import Icon_Warning from '../../assets/Icon_Warning.svg'; import arrowIcon from '../../assets/arrowIcon.svg'; import tipIcon from '../../assets/tipIcon.svg'; import questionSuccess from '../../assets/questionSuccess.svg'; import selectIcon from '../../assets/selectIcon.svg'; import arrowIconBlue from '../../assets/arrowIconBlue.svg'; import { base64ToText, isJsonString } from '../utils/index' import { Terminal } from 'xterm'; import EditorComponent from '../RichEditor'; const active = (props: any) => { // 活动对象 const [activeValue, setActiveValue] = useState({}) const [selectKey, setSelectKey] = useState([]) const [isSubmit, setIsSubmit] = useState(false) const [ifSuccess, setIfSuccess] = useState(undefined)//是否成功 const [fail, setFail] = useState(false) const [optionAnswer, SetOptionAnswer] = useState([]) const [tipShow, setTipShow] = useState(true)//提示框是否显示 const [auxiliary, setAuxiliary] = useState([]) const [execExperiment, setExecExperiment] = useState(false)//是否执行完成 const [isValidate, setIsValidate] = useState(false)//是否执行完成 const [contValue, setContValue] = useState(0)//获得的分数 const [mark, setMark] = useState(false) const [localUrl, setLocalUrl] = useState() const [validateCode, setValidateCode] = useState() const [codePath, setCodePath] = useState() //演示脚本 // const [component, setComponent] = useState(null);//mardown语法 //是否需要连接校验 const [ifShell, setIfShell] = useState() // websocket实例 const [websocket, setWebsocket] = useState() // const [mark] = useState(false) const getActive = (fileId: string, workdir: boolean) => { let url = '' if (workdir) { url = `${localUrl}&file=${encodeURIComponent(fileId)}&workdir=${workdir}` } else { url = `${localUrl}&file=${encodeURIComponent(fileId + '.json')}` } console.log(url); fetch(url, { method: 'GET' }) .then(response => response.json()) .then(data => { const _data = base64ToText(data.data) if (!workdir) { setActiveValue(isJsonString(_data) ? JSON.parse(_data) : {}) } else { setCodePath(_data) } }) .catch(error => { console.error(error); // 处理错误 }); } //判断数组是否相同 const areArraysEqual = (arr1: any, arr2: any) => { if (arr1.length !== arr2.length) { return false; } const set1 = new Set(arr1); const set2 = new Set(arr2); if (set1.size !== set2.size) { return false; } return Array.from(set1).every(item => set2.has(item)); } //问答提交按钮 const submitOption = () => { // console.log('🚀', '选择题') window.postMessage({ type: 'markdown-reportData', value: { lang: props?.lang, id: isJsonString(props?.value) ? JSON.parse(props?.value)?.id ?? '' : '' } }, '*') const str1 = JSON.stringify(optionAnswer); const str2 = JSON.stringify(selectKey); if (!isSubmit) { if (!mark) { setIfSuccess(areArraysEqual(str1, str2)) } else { if (areArraysEqual(str1, str2)) { setContValue(activeValue?.score ?? 0) ifPostContValue(activeValue?.score ?? 0) } else { ifPostContValue(0) } } } setIsSubmit(true) } //执行按钮 const execBtn = () => { // console.log('🚀', '示例演示') window.postMessage({ type: 'markdown-reportData', value: { lang: props?.lang, id: isJsonString(props?.value) ? JSON.parse(props?.value)?.id ?? '' : '' } }, '*') if (props?.lang === 'experiment' && !execExperiment) { window.postMessage({ type: 'markdown-layout', value: { data: activeValue } }, '*') setExecExperiment(true) if (auxiliary?.length < 1) { setContValue(activeValue?.score ?? 0) ifPostContValue(activeValue?.score ?? 0) } } } //监听更新 const updateValue = (event: any) => { if (event?.data?.type === 'updateActivity' && event?.data?.id === activeValue?.id) { getActive(event?.data?.id ?? '', false) } } //校验按钮 const valitade = () => { // console.log('🚀', '编码测验') window.postMessage({ type: 'markdown-reportData', value: { lang: props?.lang, id: isJsonString(props?.value) ? JSON.parse(props?.value)?.id ?? '' : '' } }, '*') setTimeout(() => { setIsValidate(true) }, 300); if (props?.lang === 'validate') { websocket?.send(activeValue?.code + '\r') } else if (auxiliary?.length > 0) { let code = auxiliary[0]?.code websocket?.send(code + '\r') } } //是否处于评分模式 const ifPostContValue = (conValue: any) => { if (mark) { window.postMessage({ type: 'postValue', value: { value: conValue, activeID: activeValue?.id } }, '*'); } } //实验图标旋转 const rotateImg = () => { let image: any image = document.getElementById("arrowImgBlue") if (image && image.style) { if (tipShow) { image.style.transform = "rotate(180deg)"; setTipShow(!tipShow) } else { image.style.transform = "rotate(360deg)"; setTipShow(!tipShow) } } } //提示图标旋转 const rotateTipImg = () => { let image: any image = document.getElementById("arrowImg") if (image && image.style) { if (tipShow) { image.style.transform = "rotate(180deg)"; setTipShow(!tipShow) } else { image.style.transform = "rotate(360deg)"; setTipShow(!tipShow) } } } useEffect(() => { if (isJsonString(props?.value) && localUrl) { const elem = document.querySelector(`#${JSON.parse(props?.value)?.id}`) as HTMLElement if (elem?.offsetHeight > 0) { getActive(JSON.parse(props?.value)?.id ?? '', false) setIfShell(true) } else { websocket?.close() setIfShell(false) } // setActiveValue(JSON.parse(props?.value)) } }, [props, localUrl]) useEffect(() => { if (activeValue) { if (activeValue?.codePath) { getActive(activeValue?.codePath || '', true) } SetOptionAnswer(activeValue?.selected?.split(",") ?? '') setAuxiliary(activeValue?.auxiliary ?? []) if (props?.lang === 'experiment' && activeValue?.auxiliary?.length > 0) { setValidateCode(activeValue?.auxiliary[0]?.codeResult ?? '') } else { setValidateCode(activeValue?.codeResult ?? '') } setSelectKey([]) setIsSubmit(false) setIfSuccess(false) setTipShow(true) setExecExperiment(false) setIsValidate(false) setContValue(0) } }, [activeValue]) useEffect(() => { if (window.localStorage.getItem('mark') && activeValue?.id) { getActive(activeValue?.id ?? '', false) if (window.localStorage.getItem('mark') === 'true') { setMark(true) } else { setMark(false) } } else { setMark(false) } }, [window.localStorage.getItem('mark'), activeValue?.id]) useEffect(() => { if (window.localStorage.getItem('activeUrl')) { setLocalUrl(window.localStorage.getItem('activeUrl') ?? '') } }, [window.localStorage.getItem('activeUrl')]) useEffect(() => { if (props?.lang === 'question') return if (!props.url) return if (!ifShell) return const terminal = new Terminal() const ws = new WebSocket(props.url ?? "") setWebsocket(ws) let root = '' ws.onmessage = function (e: any) { let data = e.data if (typeof data === 'string') { terminal.write(data); if (!root) { root = data return } const _data = data.split('\r\n') const newData: any[] = [] if (_data?.length > 0) { _data.forEach((item: any) => { newData.push(item.replace(/>/g, "").trim()); }) } if (newData.includes(validateCode)) { setIfSuccess(true) setContValue(activeValue?.score ?? 0) ifPostContValue(activeValue?.score ?? 0) } else { setFail(true) } } else { console.error('格式错误'); } } return () => { ws?.close() } }, [props.url, validateCode, ifShell]) useEffect(() => { if (!activeValue?.id) return window.addEventListener("message", updateValue); return () => { window.removeEventListener("message", updateValue); } }, [activeValue?.id]) useEffect(() => { if (ifSuccess) { return } if (fail) { setIfSuccess(ifSuccess ?? false) } }, [ifSuccess, fail]) return (
{props?.lang === 'question' &&
选择题
{mark && {activeValue?.score ?? 0}分} {activeValue?.category === "checkbox" ? '多选' : '单选'}
题目描述
{ activeValue?.options?.map((v: any) =>
{ setIsSubmit(false) setContValue(0) let selectValue = activeValue?.category === "checkbox" ? JSON.parse(JSON.stringify(selectKey)) : [] if (selectValue.includes(v?.key)) { selectValue.splice(selectValue.indexOf(v?.key), 1); } else { selectValue.push(v?.key); } setSelectKey(selectValue) }}> { selectKey.includes(v?.key) && activeValue?.category === 'radio' &&
} { selectKey.includes(v?.key) && activeValue?.category === 'checkbox' &&
}
{v?.value}
) }
{isSubmit && !mark && (ifSuccess ?
回答正确
:
回答错误,请重新作答!
)}
{isSubmit && !ifSuccess && !mark && auxiliary?.length > 0 && auxiliary[0]?.type === 'tip' &&
提示
{tipShow &&
}
}
{selectKey?.length > 0 ?
{isSubmit ? `已提交` : `${activeValue?.buttonName ?? '确认'}`}
:
{`${activeValue?.buttonName ?? '确认'}`}
}
} {(props?.lang === 'experiment') &&
0 ? activeValue?.auxiliary[0]?.required ?? false : false} data-nextcorrect={activeValue?.auxiliary?.length > 0 ? activeValue?.auxiliary[0]?.requiredCorrect ?? false : false} data-validate={isValidate} > {/* 校验指令 */} {
{props?.lang === 'validate' ? '编码测验' : '示例演示'} {mark && {activeValue?.score ?? 0}分}
演示描述
{/*
{}
*/}
{ifSuccess !== undefined && isValidate && !mark &&
{ifSuccess ?
校验成功!
:
校验错误,请重新校验!
}
}
} {/* 实验指令 */} {props?.lang === 'experiment' && activeValue?.showCode && (!execExperiment || auxiliary?.length < 1) &&
演示脚本
{tipShow &&
{codePath ? codePath : activeValue?.code}
}
}
{props?.lang === 'experiment' ?
{execExperiment && auxiliary?.length > 0 && auxiliary[0]?.type === 'validate' &&
{ setExecExperiment(false) setIsValidate(false) setIfSuccess(undefined) setFail(false) }}>上一步
{ valitade() }}>{auxiliary[0]?.buttonName || '确认'}
}
0 && auxiliary[0]?.type === 'validate' ? 'none' : 'block' }} className='exec-btn' onClick={execBtn} data-type={'exec'} data-value={JSON.stringify(activeValue)}>{activeValue?.buttonName || '确认'}
: '' }
} {(props?.lang === 'validate') &&
0 ? activeValue?.auxiliary[0]?.required ?? false : false} data-nextcorrect={activeValue?.auxiliary?.length > 0 ? activeValue?.auxiliary[0]?.requiredCorrect ?? false : false} data-validate={isValidate} > {/* 实验或校验题目 */} {/* {props?.lang !== 'validate' && (!execExperiment || auxiliary?.length < 1) &&
{props?.lang === 'validate' ? '编码测验' : '示例演示'}
{mark && {activeValue?.score ?? 0}分}
}
{activeValue?.title ?? ''}
*/} {/* 校验指令 */} {((auxiliary?.length > 0 && execExperiment) || props?.lang === 'validate') &&
{props?.lang === 'validate' ? '编码测验' : '示例演示'} {mark && {activeValue?.score ?? 0}分}
演示描述
{activeValue?.ansGuide &&
答题引导
} {activeValue?.ansGuide &&
} {ifSuccess !== undefined && isValidate && !mark &&
{ifSuccess ?
校验成功!
:
校验错误,请重新校验!
}
}
} {/* 实验指令 */} {props?.lang === 'experiment' && activeValue?.showCode && (!execExperiment || auxiliary?.length < 1) &&
实验指令
{tipShow &&
{activeValue?.code ?? ''}
}
} {ifSuccess !== undefined && isValidate && !mark && !ifSuccess && (auxiliary?.length > 0 && (auxiliary[0]?.type === 'tip' || (auxiliary[0]?.auxiliary?.length > 0 && auxiliary[0]?.auxiliary[0]?.type === 'tip'))) &&
提示
{tipShow &&
{props?.lang === 'validate' ? auxiliary[0]?.description ?? '' : auxiliary[0]?.auxiliary[0]?.description ?? ''}
}
}
{props?.lang === 'experiment' ?
{execExperiment && auxiliary?.length > 0 && auxiliary[0]?.type === 'validate' &&
{ setExecExperiment(false) setIsValidate(false) setIfSuccess(undefined) setFail(false) }}>上一步
{ valitade() }}>{auxiliary[0]?.buttonName || '确认'}
}
0 && auxiliary[0]?.type === 'validate' ? 'none' : 'block' }} className='exec-btn' onClick={execBtn} data-type={'exec'} data-value={JSON.stringify(activeValue)}>{activeValue?.buttonName || '确认'}
: '' } {props?.lang === 'validate' &&
{ valitade() }}>{activeValue?.buttonName || '确认'}
}
}
); }; export default active;